#include <linux/init.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/slab.h>

struct my_work_struct {
    struct work_struct work;
    char *data;
    int len;
};

static struct workqueue_struct *my_workqueue;

static void oops_trigger_work(struct work_struct *work) {
    struct my_work_struct *my_work = container_of(work, struct my_work_struct, work);

    printk(KERN_INFO "Executing work item in: %s\n", __func__);

    // 故意引发空指针访问，触发 Oops
    *(my_work->data) = 'A';  // data 为 NULL 时会崩溃

    printk(KERN_INFO "Work completed\n");
}

static int __init oops_demo_init(void) {
    struct my_work_struct *my_work;

    printk(KERN_INFO "Oops demo module loaded\n");

    my_workqueue = create_workqueue("oops_demo_queue");
    if (!my_workqueue) {
        printk(KERN_ERR "Failed to create workqueue\n");
        return -ENOMEM;
    }

    my_work = kmalloc(sizeof(*my_work), GFP_KERNEL);
    if (!my_work) {
        destroy_workqueue(my_workqueue);
        return -ENOMEM;
    }

    INIT_WORK(&my_work->work, oops_trigger_work);

    my_work->data = NULL;
    my_work->len = 1024;

    queue_work(my_workqueue, &my_work->work);
    return 0;
}

static void __exit oops_demo_exit(void) {
    if (my_workqueue) {
        destroy_workqueue(my_workqueue);
        printk(KERN_INFO "Workqueue destroyed\n");
    }

    printk(KERN_INFO "Oops demo module unloaded\n");
}

module_init(oops_demo_init);
module_exit(oops_demo_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A Oops example");
